package importexport;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import main.Main;
import database.Database;

public class Import {
	
	private static int BUFFER = 2048;
	
	public static boolean importZip(String path) throws Exception {
		File filesdir = new File("files");
		if (!filesdir.exists()) {
			if (!filesdir.mkdir()) {
				return false;
			}
		}
		Database db = Main.db;
		if (!unzip(path)) {
			return false;
		}
		File tempdir = new File("temp");
		if (!tempdir.exists()) {
			if (!tempdir.mkdir()) {
				return false;
			}
		}
		XmlParser parser = new XmlParser("temp");
		if (!parser.parse()) {
			return false;
		}
		for (int i = 0; i < parser.getNumberOfContacts(); i++) {
			VCard card = parser.getContact(i);
			if (card.getTitle().equals("professor") | card.getTitle().equals("assistant")) {
				db.teach.add(card.getEmail(), card.getLastName(), card.getFirstName(), card.getPhoneNumber(), "", card.getOffice(), card.getPrefix());
			}
			else if (card.getTitle().equals("student")) {
				db.stud.add(card.getEmail(), card.getLastName(), card.getFirstName(), card.getPhoneNumber(), "", card.getAltEmail());
			}
			else {
				db.contact.add(card.getEmail(), card.getLastName(), card.getFirstName(), card.getPhoneNumber(), "");
			}
			
			String filename = card.getEmail() + ".vcf";
			File oldcard = new File("temp\\" + filename);
			if (oldcard.exists()) {
				File vcarddir = new File("vcards");
				if (!vcarddir.exists()) {
					if (!vcarddir.mkdir()) {
						return false;
					}
				}
				File newcard = new File("vcards\\" + filename);
				copyFile(oldcard, newcard);
			}
		}
		for (int i = 0; i < parser.getNumberOfCourses(); i++) {
			Course course = parser.getCourse(i);
			int year = Integer.parseInt(course.getBeginYear());
			int sem = Integer.parseInt(course.getSemester());
			db.course.add(course.getName(), course.getDescription(), year, sem, "");
			for (int j = 0; j < course.getNumberOfTutors(); j++) {
				db.rCTeach.add(course.getName(), course.getTutor(j));
			}
			for (int j = 0; j < course.getNumberOfFiles(); j++) {
				String coursefile = course.getFile(j);
				File oldfile = new File(coursefile);
				if (oldfile.exists()) {
					File newfile = new File("files\\" + oldfile.getName());
					copyFile(oldfile, newfile);
				}
				coursefile = "files\\" + oldfile.getName();
				db.rCF.add(course.getName(), coursefile);
			}
		}
		for (int i = 0; i < parser.getNumberOfEvents(); i++) {
			Event event = parser.getEvent(i);
			if (event.getLesson()) {
				int day = Integer.parseInt(event.getDayOfWeek());
				int weeks = Integer.parseInt(event.getNumberOfWeeks());
				db.lesson.add(event.getStart(), event.getEnd(), event.getSummary(), event.getWarningDate(), "", event.getRoom(), day, weeks, event.getCourse());
			}
			else {
				db.event.add(event.getStart(), event.getEnd(), event.getSummary(), false, event.getWarningDate(), "");
			}
		}
		for (int i = 0; i < parser.getNumberOfProjects(); i++) {
			Project project = parser.getProject(i);
			int grades = Integer.parseInt(project.getGrades());
			if (project.getType().equals("task")) {
				db.task.add(project.getName(), project.getDescription(), project.getDone(), grades, "");
			}
			else if (project.getType().equals("project")) {
				db.proj.add(project.getName(), project.getDescription(), project.getDone(), grades, "", project.getProjectPlanning());
				for (int j = 0; j < project.getNumberOfMembers(); j++) {
					db.rPS.add(project.getName(), project.getProjectMember(j));
				}
			}
			else if (project.getType().equals("exam")) {
				Character type = project.getExamType().toCharArray()[0];
				Boolean oral = project.getExamOral();
				Boolean done = project.getDone();
				Integer grades2 = grades;
				Integer hours = Integer.parseInt(project.getExamHours());
				db.exam.add(project.getName(), project.getDescription(), done, grades2, "", project.getExamRoom(), hours, type, oral);
			}
			for (int j = 0; j < project.getNumberOfDeadlines(); j++) {
				db.event.add(project.getDeadline(j), project.getDeadline(j), project.getDeadlineDesc(j), true, project.getDeadline(j), "");
				db.rTE.add(project.getName(), project.getDeadline(j), project.getDeadlineDesc(j));
			}
			for (int j = 0; j < project.getNumberOfFiles(); j++) {
				String taskfile = project.getFile(j);
				File oldfile = new File(taskfile);
				if (oldfile.exists()) {
					File newfile = new File("files\\" + oldfile.getName());
					copyFile(oldfile, newfile);
				}
				taskfile = "files\\" + oldfile.getName();
				db.rTF.add(project.getName(), taskfile);
			}
			if (project.getCourse() != null) {
				db.rCTask.add(project.getCourse(), project.getName());
			}
		}
		File deldir = new File("temp");
		recursiveDelete(deldir);
		return true;
	}
	
	private static void recursiveDelete(File dirPath) {
	    String[] ls = dirPath.list();
	    for (int idx = 0; idx < ls.length; idx++) {
	    	File file = new File(dirPath, ls[idx]);
	    	if (file.isDirectory())
	        recursiveDelete(file);
	    	file.delete();
	    }
	    dirPath.delete();
	}
	
	private static boolean unzip(String path) throws IOException {
		BufferedOutputStream dest = null;
        FileInputStream fis;
		try {
			fis = new FileInputStream(path);
		} catch (FileNotFoundException e) {
			return false;
		}
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
        ZipEntry entry;
        new File("temp").mkdir();
        while((entry = zis.getNextEntry()) != null) {
           int count;
           byte data[] = new byte[BUFFER];
           FileOutputStream fos = new FileOutputStream("temp\\" + entry.getName());
           dest = new BufferedOutputStream(fos, BUFFER);
           while ((count = zis.read(data, 0, BUFFER)) != -1) {
              dest.write(data, 0, count);
           }
           dest.flush();
           dest.close();
        }
        zis.close();
		
		return true;
	}
	
	private static void copyFile(File in, File out) throws IOException {
	    FileChannel inChannel = new FileInputStream(in).getChannel();
	    FileChannel outChannel = new FileOutputStream(out).getChannel();
	    try {
	        inChannel.transferTo(0, inChannel.size(), outChannel);
	    } 
	    catch (IOException e) {
	        throw e;
	    }
	    finally {
	        if (inChannel != null) inChannel.close();
	        if (outChannel != null) outChannel.close();
	    }
	}
	
}
